const knex = require('../../db/knex')
const randomString = require("../../utils/randomString");
const _ = require('lodash')

async function submitAnswer(params, res) {
    let {studentInfo, selectedResult} = params
    let uid = randomString(5)
    console.log(params, '提交情况')
    for (const o of selectedResult) {
        const ind = selectedResult.indexOf(o);
        let {checkedList: checked_list, totalScore: total_score, question_id, questionnaire_id} = selectedResult[ind]
        let {stu_name: student_name, stu_id: student_id} = studentInfo
        let finalResult = {
            checked_list: checked_list.join(" "), total_score, question_id, questionnaire_id,
            student_name, student_id, uid
        }
        try {
            await knex.transaction(async trx => {
                await trx('answer_list').insert(finalResult)

            })
        } catch (e) {
            console.log(e)
            throw e
        }
    }
    res.send({
        msg: "提交成功"
    })

}

async function fetchSubmitted(params, res) {
    let {id} = params
    console.log(id, 'id呢')
    try {
        await knex.transaction(async trx => {//这个代码会查询表a中id字段等于给定的所有数据，并在表a和表b之间进行联表查询，
            // 返回表a中满足条件的所有字段和表b中与之对应的id等于给定的id字段。其中 select 方法指定了查询结果中的字段列表，
            // 第一个参数是表a中的所有字段，第二个参数是表b中的id字段，where 方法和 andWhere 方法分别用于指定表a中id字段和表b中id字段满足的条件。
            let data = await trx.select('answer_list.*', 'published_questionnaire.questionnaire_name')
                .from('answer_list')
                .join('published_questionnaire', 'answer_list.questionnaire_id', 'published_questionnaire.questionnaire_id')
                .where('answer_list.questionnaire_id', id)
                .andWhere('published_questionnaire.questionnaire_id', id)
//处理数据
            // 将data里uid相同的对象进行合并为一个对象
            const mergedData = _.map(_.groupBy(data, 'uid'), group => {
                const {checked_list, question_id, total_score, ...rest} = group[0];
                // 将 checkedResult 属性赋值为一个包含 question_id 和 checked_list 的对象数组
                const checkedResult = _.map(group, item => _.pick(item, ['question_id', 'checked_list']));
                // 将相同 uid 对象的 total_score 相加
                const newTotalScore = _.sumBy(group, 'total_score');
                return {
                    ...rest,
                    checkedResult,
                    total_score: newTotalScore,
                };
            });
            res.send({
                data: mergedData
            })
        })

    } catch (e) {
        console.log(e)
    }

}

async function deleteAnsweredQuestionnaire(params, res) {
    let {uid} = params
    try {
        await knex.transaction(async trx => {
            await trx('answer_list').del().where("uid", uid)

        })
        res.status(200).send({
            msg: "删除成功"
        })
    } catch (e) {
        console.log(e)
    }

}

async function countPercentage(params, res) {//计算百分比
    let {id} = params //id是问卷id

    try {
        await knex.transaction(async trx => {
            let res1 = await trx('answer_list').select('checked_list', 'question_id').where('questionnaire_id', id)
            let result = _(res1)
                .groupBy('question_id') // 按照 question_id 进行分组
                .map((groupItems) => ({
                    checked_list: groupItems.map((item) => item.checked_list).join(' '), // 合并每个组内的 checked_list
                    question_id: groupItems[0].question_id, // 使用第一个元素的 question_id 作为新对象的值
                }))
                .value();
            console.log(result, '结果1')
            //计算每个选项出现的频率
            result = _.map(result, obj => {
                // 将 checked_list 属性通过空格分隔成一个字符串数组 options,使用正则表示字符串之间的多个空格,避免把多余空格变成数组元素
                const options = _.split(obj.checked_list.trim(), /\s+/);

                // 使用 _.countBy 方法计算每个选项出现的次数，并将其存储到对象 counts 中
                const counts = _.countBy(options);

                // 使用 _.mapValues 方法遍历 counts 对象，将每个出现次数除以数组长度并乘以 100，将其转换为频率
                const frequencies = _.mapValues(counts, count => (count / options.length) * 100);

                // 将 question_id 属性和 frequencies 对象合并成一个新的对象，并将其返回
                return {question_id: obj.question_id, ...frequencies};
            });


            console.log(result, '结果')
            res.send({
                data: result
            })

        })
    } catch (e) {
        console.log(e)
    }

}

module.exports = {
    submitAnswer,
    fetchSubmitted,
    deleteAnsweredQuestionnaire,
    countPercentage
}

// 解释：
// 1. countBy函数将一个数组或对象中每个元素出现次数计数，返回一个对象。这里使用countBy函数对每个元素中的字符串列表计数。
// 2. split函数将一个字符串根据指定分隔符分隔成多个子字符串，返回一个数组。这里使用split函数将每个元素的字符串列表通过空格分隔成一个字符串数组。
// 3. values函数将一个对象中所有的值提取出来，返回一个数组。这里使用values函数将每个元素中的计数值提取出来。
// 4. reduce函数将一个数组中的所有元素进行累加/合并操作，最终返回一个值。这里使用reduce函数将每个元素中的计数值相加得到总计数。
// 5. mapValues函数将一个对象中每个值进行处理，并返回一个新的对象，key与原对象相同。这里使用mapValues函数对每个元素中的计数对象进行处理，计算每个元素所占的百分比。
// 6. Math.round函数将传入的数值四舍五入为最接近的整数。
// 7. 输出结果数组。
